﻿using Iot.Device.Sht3x;

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Device.Gpio;
using System.Device.I2c;
using System.Text;
using System.Threading;
using System.Linq;
using System.IO.Ports;
using IotDeviceToolHepler.WiringOPSharp;
using Iot.Device.Pn532;

namespace IotDeviceToolHepler.Utils
{

    /// <summary>
    /// 串口调用示例
    /// </summary>
    public class UtilsSerial
    {
     
        private static object obj = new object();
        private static string _portName = "";
        private static int _baudRate = 0;
        private static SerialPort serialPort;
        static byte[] recData;
        static string getPortDataresult;
        /// <summary>
        /// 串口调用,发送字节组
        /// </summary>
        /// <param name="portName">com4</param>
        /// <param name="baudRate">波特率4800</param>
        /// <param name="sendData">010300060001640B</param>
        /// <returns></returns>
        public static string getPortData(string portName, int baudRate, string sendData)
        {
            lock (obj)
            {
                try
                {
                    if (portName != _portName || _baudRate != baudRate)
                    {                       
                        //波特率或串口发生变化，先关闭串口，重新打开串口
                        if (serialPort != null && serialPort.IsOpen)
                        {
                            serialPort.Close();
                            serialPort.Dispose();
                        }
                   
                        serialPort = new SerialPort(portName, baudRate, Parity.None, 8, StopBits.One);
                        serialPort.ReadBufferSize = 2096;
                        serialPort.WriteBufferSize = 1048;
                        serialPort.Open();
                        _portName = portName;
                        _baudRate = baudRate;
                    }
                   // recData = new byte[serialPort.BytesToRead];
                   // serialPort.Read(recData, 0, recData.Length);
                    byte[] sendByte = new UtilsDataTypeChange().strToHexByte(sendData);
                    //发送数据
                    serialPort.Write(sendByte, 0, sendByte.Length);
                    //读取返回数据
                    int count = 1;
                    int br1 = 0;
                    int br2 = 0;
                    while (true)
                    {
                        br1 = serialPort.BytesToRead;
                        Thread.Sleep(30);
                        br2 = serialPort.BytesToRead;
                        if (br1 != 0 && br1 == br2)
                        {
                            break;
                        }
                        count++;
                        if (br1 == 0 && count > 5)
                        {
                            break;
                        }
                        else if (br1 > 0 && count > 20)
                        {
                            break;
                        }
                    }
                    recData = new byte[serialPort.BytesToRead];
                    serialPort.Read(recData, 0, recData.Length);
                    getPortDataresult = new UtilsDataTypeChange().byteToHexStr(recData);  
                    return getPortDataresult;
                }
                catch (Exception ex)
                {
                    if (serialPort != null && serialPort.IsOpen)
                    {
                        serialPort.Close();
                        serialPort.Dispose();
                    }
                    Console.WriteLine(ex.ToString());
                    return "";
                }
            }
        }
        /// <summary>
        /// 串口调用,发送字节组
        /// </summary>
        /// <param name="portName"></param>
        /// <param name="command"></param>
        public void getDataAndWriteByte(string portName, string command)
        {
            //string command = "\"01 03 00 02 00 02 65 CB\"";
            //string portName = "/dev/ttyS3";
            int baudRate = 9600;
            //portName树莓派调用/dev/ttyAMA0
            //portName香橙派调用/dev/ttyS3
            SerialPort serial = new SerialPort(portName, baudRate, Parity.None, 8, StopBits.One);
            serial.Open();
            // DataReceived是串口类的一个事件，通过+=运算符订阅事件，如果串口接收到数据就触发事件，调用DataReceive_Method事件处理方法
            serial.DataReceived += new SerialDataReceivedEventHandler(getDataAndWriteByteDataReceiveMethod);
            //while (true)
            //{
            //查光照度指令
            serial.Write(new UtilsDataTypeChange().strToHexByte(command), 0, 8);
            //  Thread.Sleep(2000);
            // }
        }

        /// <summary>
        /// getDataAndWriteByte接收信息事件处理方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void getDataAndWriteByteDataReceiveMethod(object sender, SerialDataReceivedEventArgs e)
        {
            //sender是事件触发对象，通过它可以获取到mySerialPort
            SerialPort serialport = (SerialPort)sender;
            int len = serialport.BytesToRead;
            byte[] recvdata = new byte[len];
            serialport.Read(recvdata, 0, len);
            var str = new UtilsDataTypeChange().byteToHexStr(recvdata);

            if (str.Length > 10)
            {
                string result = str.Substring(6, 8);
                int result16 = new UtilsDataTypeChange().hex16Convert10(result);
                Console.WriteLine("");
                //  Console.WriteLine(DateTime.Now + " 光照强度:" + (result16 / 1000.0).ToString() + "lur");
            }
        }

        static SerialPort portString = null;
        /// <summary>
        /// 串口调用,适用于蓝牙模块hc-04通讯
        /// </summary>
        public void getDataAndWriteString(string portName, int baudRate, string content)
        {
            if (portString == null)
            {
                portString = new SerialPort(portName);
                portString.BaudRate = baudRate;
                portString.DataBits = 8;
                portString.Parity = Parity.None;
                portString.StopBits = StopBits.One;
                portString.Open();
                portString.DataReceived += getDataAndWriteStringPortDataReceived;
                Console.WriteLine("Serial Is Open");
            }
            if (portString.IsOpen)
            {
                // 将字符串转换为字节数组并写入串口
                byte[] dataBytes = Encoding.ASCII.GetBytes(content);
                portString.Write(dataBytes, 0, dataBytes.Length);
            }
        }
        private void getDataAndWriteStringPortDataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            var s = sender as SerialPort;
            if (s.BytesToRead > 0)
            {
                Thread.Sleep(50);
            }
            byte[] recData = new byte[s.BytesToRead];
            s.Read(recData, 0, recData.Length);
            var str = Encoding.Default.GetString(recData);
            Console.WriteLine(str);
        }


        /// <summary>
        /// 串口调用,发送char
        /// </summary>
        public void getDataAndWriteChar(string portName, int baudRate)
        {
            var port = new SerialPort(portName);
            port.BaudRate = baudRate;
            port.DataBits = 8;
            port.Parity = Parity.None;
            port.StopBits = StopBits.One;
            port.Open();
            if (port.IsOpen)
            {
                Console.WriteLine("Serial Is Open");
                char[] cs = new char[] { 'c', 'x', 'd' };
                port.Write(cs, 0, cs.Length);
                Console.WriteLine("Serial Is Close");
                port.DataReceived += getDataAndWriteCharPortDataReceived;
            }
        }
        private void getDataAndWriteCharPortDataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            var s = sender as SerialPort;
            int len = s.ReadByte();
            var chars = new byte[len];
            s.Read(chars, 0, len);
            var str = Encoding.Default.GetString(chars);
            Console.WriteLine(str);
        }

        /// <summary>
        /// 通过WiringOP 操作串口
        /// </summary>
        public void getDataAndWriteStringbyWiringOP()
        {
            string device = "/dev/ttyS3";
            if (Setup.WiringPiPiSetup() < 0)
            {
                Console.WriteLine("Wringpi setup failed.");
                return;
            }

            int fd = Serial.SerialOpen(device, 115200);
            if (fd < 0)
            {
                Console.WriteLine("Serial ppen failed.");
                return;
            }
            //异步执行串口读取  
            Task readTask = Task.Run(() => getDataAndWriteStringbyWiringOpDataReceived(fd));
            //发送
            while (true)
            {
                Console.Write("TX:");
                string send = Console.ReadLine();
                if (string.IsNullOrEmpty(send))
                {
                    continue;
                }
                if (send == "exit")
                {
                    break;
                }
                Serial.SerialPuts(fd, send);
            }
            Serial.SerialClose(fd);
            Console.WriteLine("Press any key to exit...");
            Console.ReadKey(false);
        }

        public void getDataAndWriteStringbyWiringOpDataReceived(int fd)
        {
            while (true)
            {
                StringBuilder sb = null;
                while (Serial.SerialDataAvail(fd) > 0)
                {
                    int read = Serial.SerialGetchar(fd);
                    if (read < 0)
                    {
                        Serial.SerialFlush(fd);
                        break;
                    }
                    else
                    {
                        //Remove \r or \n
                        if (read == 10 || read == 13)
                        {
                            continue;
                        }
                        else
                        {
                            if (sb == null)
                            {
                                sb = new StringBuilder();
                            }
                            sb.Append((char)read);
                        }
                    }
                }
                if (sb != null)
                {
                    string readStr = sb.ToString();
                    if (!string.IsNullOrWhiteSpace(readStr))
                    {
                        Console.WriteLine($"RX:{sb.ToString()}");
                    }
                }
            }
        }
    }
}


